package com.yonyou.wdt.job;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yonyou.wdt.entity.DataConnectionTypeEnum;
import com.yonyou.wdt.entity.QueryDto;
import com.yonyou.wdt.job.config.BaseConfig;
import com.yonyou.wdt.service.YonsuiteService;
import com.yonyou.wdt.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName YsPurOrderToWdtJob
 * @Description YS销售订单同步旺店通原始单
 * @Author HuangWb
 * @Date 2024/4/26 17:08
 */
@Component
public class YsSaleOrderToWdtJob extends BaseConfig {

    private final WdtConfigProperties configProperties;

    private static final Logger logger = LoggerFactory.getLogger(YsSaleOrderToWdtJob.class);
    private static final String JOB_CLASS="maoEr003";

    @Autowired
    public YsSaleOrderToWdtJob(WdtConfigProperties configProperties) {
        this.configProperties = configProperties;
    }
    @Resource
    private YonsuiteService yonsuiteService;
    /**
     * @Author Huangwb
     * @Description YS销售订单同步旺店通原始单
     * @Date 2024/4/26 17:41
     **/
    @XxlJob("ysSaleOrderToWdtJob")
    public ReturnT<String> purOrderToWdtPurJob(String params) {
        String param = XxlJobHelper.getJobParam();
        Map<String, Object> map = new HashMap<>();
        if (param != null && !param.isEmpty()) {
            List<String> timeRange = Arrays.asList(param.split("\\|"));
            if (timeRange.size() == 2) {
                map.put("Start", timeRange.get(0));
                map.put("End", timeRange.get(1));
            } else {
                // 单据编码
                map.put("code", param);
            }
        } else {
            map.put("Start", DateUtils.getStartDateBy10m());
            map.put("End", DateUtils.getEndDateBy10m());
        }
        // 处理相关业务
        QueryDto dto = new QueryDto();
        dto.setTenantId(getYsTenantId());
        dto.setAppKey(getYsAppKey());
        dto.setAppSecret(getYsAppSecret());
        // 获取YS系统租户动态域名信息
        ReturnT<String> isReturn2 = getYsDynamicDomainName(JOB_CLASS,dto);
        // 域名获取失败
        if (isReturn2 != null) return isReturn2;
        try {
            // 根据客户
            Object o = RedisUtils.get(dto.getTenantId() + ":2BCust");
            if (o==null){
                InsertLogger(JOB_CLASS,null, "0", "YS销售订单查询失败，未找到2B客户");
            }
            List<JSONObject> list = JSONUtil.toList(JSONUtil.toJsonStr(o), JSONObject.class);
            ArrayList<JSONObject> ysSaleOrderRecord = getYsSaleOrderRecord(map, dto,list);
            if (!ysSaleOrderRecord.isEmpty()) {
                // 查询YS仓库档案列表
                HashMap<String, String> ckData = YsQueryUtil.getCkData(dto,yonsuiteService);
                //自定义档案列表查询
                HashMap<String, String> custData = YsQueryUtil.getFhdpDef(dto,yonsuiteService);

                int index = 1;
                Map<String, List<JSONObject>> groupByIdMap = groupById(ysSaleOrderRecord);
                logger.info("当前时间段：{}至{}销售订单数据有：{}条", map.get("Start"), map.get("End"), groupByIdMap.keySet().size());
                for (Map.Entry<String, List<JSONObject>> idKey : groupByIdMap.entrySet()) {
                    List<JSONObject> value = idKey.getValue();
               /* for (JSONObject jsonObject : ysSaleOrderRecord) {*/
                    // 单据号
                    String ysCode = value.get(0).getStr("code");
                    // 解析数据，组装旺店通请求数据,调用旺店通接口保存数据
                    try {
                        assembleRequest(value,ckData,list,dto,custData);
                    } catch (Exception e) {
                        logger.error("YS销售订单：{}同步旺店通失败：{}", ysCode, e.getMessage());
                        InsertLogger(JOB_CLASS,ysCode, "0", "YS销售订单：{"+ysCode+"}同步旺店通失败："+e.getMessage());
                    }
                    // 旺店通接口频率问题处理
                    if (ysSaleOrderRecord.size() >= 60) {
                        if (ysSaleOrderRecord.size() == 60) {
                            if (index == 25) {
                                Thread.sleep(1500);
                            }
                        } else {
                            Thread.sleep(1000);
                        }
                    }
                    index++;
                }
            }
        } catch (Exception e) {
            logger.error("Error occurred", e);
            logger.error("YS销售订单同步旺店通原始单失败：" + e.getMessage());
            return ReturnT.FAIL;
        }
        logger.info("  --  YS销售订单同步旺店通原始单任务执行完成  --  ");
        return ReturnT.SUCCESS;
    }

    private Map<String, List<JSONObject>> groupById(ArrayList<JSONObject> ysPurinrecordList) {
        return ysPurinrecordList.stream().collect(Collectors.groupingBy(jsonObject -> jsonObject.getStr("id")));
    }


    /**
     * @return
     * @Author Huangwb
     * @Description 组装旺店通接口请求查询并调用旺店通接口保存数据
     * @Date 10:48 2023/5/23
     * @Param
     **/
    private void assembleRequest(List<JSONObject> jsonObjectList,HashMap<String, String> ckData,List<JSONObject> list,QueryDto dto,HashMap<String, String> custData){
        // 旺店通销售订单新建请求
        // 单据号
        JSONObject jsonObject = jsonObjectList.get(0);
        String ysCode = jsonObject.getStr("code");
        /*Optional<JSONObject> first = list.stream().filter(o -> o.getStr("id").equals(jsonObject.getStr("agentId"))).findFirst();
        String shopNo = null;
        if (first.isPresent()){
            shopNo=first.get().getStr("code");
        }*/
        HashMap<String, Object> reqMap = new HashMap<>();
        JSONObject jsonObject1 = jsonObject.getJSONObject("orderDefineCharacter");
        if(jsonObject1==null || StringUtils.isBlank(jsonObject1.getStr("maoer03"))){
            InsertLogger(JOB_CLASS,ysCode, "0", "销售订单"+ysCode+"旺店通发货店铺未输入，请同步后重试");
            throw new RuntimeException("销售订单"+ysCode+"旺店通发货店铺未输入，请同步后重试");
        }
        String shopNo= custData.get(jsonObject1.getOrDefault("maoer03", "").toString());

        reqMap.put("shop_no",shopNo);

        HashMap<String, Object> tradeMap = new HashMap<>();
        Map<String, String> orderShippingAddress = AddressResolutionUtil.addressResolution(jsonObject.getStr("receiveAddress").trim().replace(" ",""));
        tradeMap.put("tid",ysCode);//原始单号
        tradeMap.put("trade_status",30);//平台状态
        tradeMap.put("delivery_term",1);//发货条件
        tradeMap.put("pay_time",jsonObject.getStr("createTime"));//支付时间
        tradeMap.put("buyer_nick","未知");//客户网名
        tradeMap.put("receiver_name",jsonObject.getStr("receiver"));//收件人
        tradeMap.put("receiver_province",orderShippingAddress.get("province"));//省份
        tradeMap.put("receiver_city",orderShippingAddress.get("city"));//城市
        tradeMap.put("receiver_district",orderShippingAddress.get("county"));//区县
        tradeMap.put("receiver_address",orderShippingAddress.get("detail"));//地址详情
        tradeMap.put("receiver_mobile",jsonObject.getStr("receiveMobile"));//手机
        // 仓库编码
        String warehouse = ckData.get(jsonObject.getOrDefault("stockId", "").toString());
        tradeMap.put("warehouse_no",warehouse);//仓库编号

        ArrayList<HashMap<String, Object>> orderList = new ArrayList<>();

        BigDecimal reight=BigDecimal.ZERO;
        BigDecimal codAmount=BigDecimal.ZERO;
        BigDecimal paid =BigDecimal.ZERO;
        for (JSONObject detailJsonObject : jsonObjectList) {
            HashMap<String, Object> orderMap = new HashMap<>();
            String ysProduct = detailJsonObject.getStr("productCode");
            // 获取Redis中物料档案信息
            JSONObject redisPrJson = (JSONObject) RedisUtils.get(dto.getTenantId() + ":product:" + ysProduct);
            if (redisPrJson == null) {
                // 保存同步错误日志，未找到对应物料档案信息
                logger.error("存在未同步YS系统物料数据：{}，请同步后重试", ysProduct);
                InsertLogger(JOB_CLASS,ysCode, "0", "存在未同步YS系统物料数据："+ysProduct+"，请同步后重试");
                throw new RuntimeException("存在未同步YS系统物料数据："+ysProduct+"，请同步后重试");
            }
            orderMap.put("oid",detailJsonObject.getStr("orderId")+"_"+detailJsonObject.getStr("orderDetailId"));//子订单编号
            BigDecimal qty = detailJsonObject.getBigDecimal("qty");
            orderMap.put("num", qty);//数量
            //BigDecimal oriTaxUnitPrice = detailJsonObject.getBigDecimal("oriTaxUnitPrice");
            BigDecimal oriTaxUnitPrice=BigDecimal.ZERO;
            orderMap.put("price", oriTaxUnitPrice);//单价
            orderMap.put("status",30);//状态
            orderMap.put("refund_status",0);//退款状态
            orderMap.put("goods_id",ysProduct);//平台货品ID
            orderMap.put("goods_no",ysProduct);//货品编码
            String wdtSpecNo = redisPrJson.getStr("barCode");
            if (StringUtils.isBlank(wdtSpecNo)) {
                // 保存同步错误日志，未找到对应物料档案信息
                logger.error("YS系统物料数据：{}，未维护条形码。请同步后重试", ysProduct);
                InsertLogger(JOB_CLASS,null, "0", "YS系统物料数据："+ysProduct+"，未维护条形码。，请同步后重试");
                throw new RuntimeException("YS系统物料数据："+ysProduct+"，未维护条形码，请同步后重试");
            }
            orderMap.put("spec_id",wdtSpecNo);//平台规格ID
            orderMap.put("spec_no", wdtSpecNo);//规格编码
            orderMap.put("goods_name",detailJsonObject.getStr("productName"));//货品名称
            orderMap.put("adjust_amount",BigDecimal.ZERO);//调整
            orderMap.put("discount",BigDecimal.ZERO);//优惠
            orderMap.put("share_discount",0);//分摊优惠
          //  paid =paid.add(detailJsonObject.getBigDecimal("oriSum"));
          //  codAmount=codAmount.add(qty.divide(oriTaxUnitPrice));
          //  reight=reight.add(detailJsonObject.getBigDecimal("reight"));
            orderList.add(orderMap);
        }
        tradeMap.put("post_amount",reight);//邮费
        tradeMap.put("cod_amount",BigDecimal.ZERO);//货到付款金额
        tradeMap.put("ext_cod_fee",BigDecimal.ZERO);//货到付款买家费用
        tradeMap.put("other_amount",BigDecimal.ZERO);//其它收费
        tradeMap.put("paid",paid);//已付
        tradeMap.put("order_list",orderList);//已付
        tradeMap.put("seller_memo",jsonObject.getStr("memo"));//已付
        ArrayList<HashMap<String, Object>> tradelist = new ArrayList<>();
        tradelist.add(tradeMap);
        String tradeListJson = JSONUtil.toJsonStr(tradelist);
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("shop_no", shopNo);
        params.put("trade_list", tradeListJson);
        WdtClient client = new WdtClient(configProperties.getSid(), configProperties.getKey(), configProperties.getSecret(), configProperties.getUrl());
        String res = null;
        try {
            res = client.execute("trade_push.php", params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        JSONObject response = JSONUtil.parseObj(res);
        if (null != response) {
            if (response.getInt("code") == 0) {
                // && response.getInt("code") == 0 && (response.getInt("new_count")+response.getInt("chg_count")==1)
                logger.info("YS销售订单：{} 同步旺店通原始单成功", ysCode);
                InsertLogger(JOB_CLASS, ysCode, "1", "YS销售订单：" + ysCode + "同步旺店通原始单成功。");
            } else {
                if (null != response) {
                    logger.error("YS销售订单：{} 同步旺店通原始单失败,原因：{}", ysCode, response.getStr("message"));
                    InsertLogger(JOB_CLASS, ysCode, "0", "YS销售订单：{" + ysCode + "}同步旺店通原始单失败：" +  response.getStr("message"));

                } else {
                    logger.error("YS销售订单：{} 同步旺店通原始单失败，旺店通接口未返回数据", ysCode);
                    InsertLogger(JOB_CLASS, ysCode, "0", "YS销售订单：{" + ysCode + "}同步旺店通原始单失败：旺店通接口未返回数据。");
                }
            }
        }
    }

    /**
     * @return
     * @Author Huangwb
     * @Description YS销售订单列表查询
     * @Date 10:39 2023/5/23
     * @Param
     **/
    private ArrayList<JSONObject> getYsSaleOrderRecord(Map<String, Object> map, QueryDto dto,List<JSONObject> list) throws Exception {
        HashMap<String, Object> purQueryMap = new HashMap<>();
        purQueryMap.put("pageSize", 100);
        // 单据状态
//		purQueryMap.put("status", "1");
        // 查询表头
        purQueryMap.put("isSum", false);
        ArrayList<Map<String, Object>> simpleVosList = new ArrayList<>();
        HashMap<String, Object> simpleVosMaps = new HashMap<>();
        if (null != map.get("code")) {
            // 根据单据编码查询
            simpleVosMaps.put("field", "code");
            simpleVosMaps.put("op", "eq");
            simpleVosMaps.put("value1", map.get("code"));
        }else{
            // 根据单据审核时间区间查询
            simpleVosMaps.put("field", "auditTime");
            simpleVosMaps.put("op", "between");
            simpleVosMaps.put("value1", map.get("Start"));
            simpleVosMaps.put("value2", map.get("End"));
        }
        HashMap<String, Object> statusMaps = new HashMap<>();
        statusMaps.put("field", "status");
        statusMaps.put("op", "eq");
        statusMaps.put("value1",1);
        List<String> collect = list.stream().map(obj ->obj.getStr("id")).collect(Collectors.toList());
        HashMap<String, Object> bustypeMap = new HashMap<>();
        bustypeMap.put("field", "agentId");
        bustypeMap.put("op", "in");
        bustypeMap.put("value1", collect);
        simpleVosList.add(bustypeMap);
        simpleVosList.add(simpleVosMaps);
        simpleVosList.add(statusMaps);
        purQueryMap.put("simpleVOs", simpleVosList);
        int pageIndex = 1;
        ArrayList<JSONObject> purList = new ArrayList<>();
        int errorIndex = 0;
        while (true) {
            purQueryMap.put("pageIndex", pageIndex);
            JSONObject purJson = yonsuiteService.saleOrderList(purQueryMap, dto);
            if ("200".equals(purJson.getStr("code"))) {
                if (null != purJson.getJSONObject("data") && null != purJson.getJSONObject("data").getJSONArray("recordList")) {
                    JSONArray purJsonArray = purJson.getJSONObject("data").getJSONArray("recordList");
                    for (Object pur : purJsonArray) {
                        purList.add((JSONObject) pur);
                    }
                }
                if (purJson.getJSONObject("data").getInt("recordCount") <= pageIndex * 100) {
                    break;
                }
                // 接口执行频率问题处理
                int endPageIndex = purJson.getJSONObject("data").getInt("endPageIndex");
                if (endPageIndex >= 60) {
                    if (endPageIndex == 60) {
                        if (pageIndex == 25) {
                            Thread.sleep(1500);
                        }
                    } else {
                        Thread.sleep(1000);
                    }
                }
                pageIndex++;
            } else {
                if (errorIndex < 10) {
                    errorIndex++;
                    logger.error("查询YS销售订单第：{}，页失败：{},延迟一秒查询", pageIndex, purJson.getOrDefault("message", "接口未返回数据"));
                    Thread.sleep(1000);
                } else {
                    // 多次失败， 退出定时任务排查原因
                    logger.error("定时任务多次执行失败，此次任务作废");
                    return new ArrayList<>();
                }
            }
        }
        return purList;
    }

}
